package com.example.trb.advice;

import com.example.trb.util.result.CommonResult;
import com.example.trb.util.result.SysReturnCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import java.util.stream.Collectors;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    @Value("${spring.servlet.multipart.max-file-size}")
    String maxUploadSize;

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public CommonResult handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        log.info("{}", e.getMessage(), e);
        SysReturnCode code = SysReturnCode.BAD_REQUEST;
        return CommonResult.fail(code.code, "上传文件的格式有问题或不支持");
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public CommonResult handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        log.info("{}", e.getMessage(), e);
        SysReturnCode code = SysReturnCode.BAD_REQUEST;
        return CommonResult.fail(code.code, "请求参数缺失");
    }

    /**
     * 请求的信息无法读取
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public CommonResult handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.info("{}", e.getMessage(), e);
        SysReturnCode code = SysReturnCode.BAD_REQUEST;
        return CommonResult.fail(code.code, "不合法的请求");
    }

    /**
     * 用于捕获数据校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public CommonResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        SysReturnCode code = SysReturnCode.REQUEST_ARGUMENT_ERROR;
        String data = e.getBindingResult().getFieldErrors()
                .stream()
                .map(fieldError -> {
                    return String.format("[%s:%s]\n", fieldError.getField(), fieldError.getDefaultMessage());
                }).collect(Collectors.joining(";"));
        log.info("data validate error: \n" + data);
        return CommonResult.fail(code.code, code.message, data);
    }

    /**
     * 用于捕获全局异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public CommonResult handleException(Exception e) {
        // 用于处理上传文件太大的异常，因为某些操蛋原因写在这里
        if (e instanceof MaxUploadSizeExceededException) {
            log.info("file is too big, max size = " + maxUploadSize + ", error message: " + e.getMessage());
            SysReturnCode code = SysReturnCode.BAD_REQUEST;
            return CommonResult.fail(code.code, "上传的文件太大了，限制大小为" + maxUploadSize);
        }
        log.error("{}", e.getMessage(), e);
        SysReturnCode code = SysReturnCode.INTERNAL_SERVER_ERROR;
        return CommonResult.fail(code.code, code.message);
    }
}
